#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <time.h>

#define LED_TOGGLE _IO('L', 0)
#define LED_ON     _IO('L', 1)
#define LED_OFF    _IO('L', 2)
#define IOCTL_SET_DATA _IOW('L', 3, struct ioctl_data)
#define IOCTL_GET_DATA _IOR('L', 4, struct ioctl_data)

struct ioctl_data {
    size_t size;
    char data[256];
};

/* 记录操作耗时 */
long long get_elapsed_ns(struct timespec start, struct timespec end) {
    return (end.tv_sec - start.tv_sec) * 1000000000LL + (end.tv_nsec - start.tv_nsec);
}

void test_led_control(int fd) {
    printf("Testing LED control via IOCTL...\n");

    struct timespec start, end;

    /* 测试 LED_ON */
    clock_gettime(CLOCK_MONOTONIC, &start);
    ioctl(fd, LED_ON);
    clock_gettime(CLOCK_MONOTONIC, &end);
    printf("LED_ON operation took %lld ns\n", get_elapsed_ns(start, end));

    sleep(2);

    /* 测试 LED_OFF */
    clock_gettime(CLOCK_MONOTONIC, &start);
    ioctl(fd, LED_OFF);
    clock_gettime(CLOCK_MONOTONIC, &end);
    printf("LED_OFF operation took %lld ns\n", get_elapsed_ns(start, end));

    sleep(2);
}

void test_large_data_transfer(int fd) {
    struct ioctl_data data;
    memset(&data, 0, sizeof(data));

    struct timespec start, end;

    /* 设置数据 */
    snprintf(data.data, sizeof(data.data), "This is a large data transfer test via IOCTL!");
    data.size = strlen(data.data);

    clock_gettime(CLOCK_MONOTONIC, &start);
    if (ioctl(fd, IOCTL_SET_DATA, &data) < 0) {
        perror("Failed to set data via IOCTL");
        return;
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    printf("IOCTL_SET_DATA operation took %lld ns\n", get_elapsed_ns(start, end));

    /* 获取数据 */
    memset(&data, 0, sizeof(data));
    clock_gettime(CLOCK_MONOTONIC, &start);
    if (ioctl(fd, IOCTL_GET_DATA, &data) < 0) {
        perror("Failed to get data via IOCTL");
        return;
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    printf("IOCTL_GET_DATA operation took %lld ns\n", get_elapsed_ns(start, end));

    /* 测试 write 接口 */
    char write_data[] = "Write interface large data test!";
    clock_gettime(CLOCK_MONOTONIC, &start);
    if (write(fd, write_data, sizeof(write_data)) < 0) {
        perror("Failed to write data");
        return;
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    printf("Write operation took %lld ns\n", get_elapsed_ns(start, end));

    /* 测试 read 接口 */
    char read_data[256] = {0};
    clock_gettime(CLOCK_MONOTONIC, &start);
    if (read(fd, read_data, sizeof(read_data)) > 0) {
        clock_gettime(CLOCK_MONOTONIC, &end);
        printf("Read operation took %lld ns\n", get_elapsed_ns(start, end));
        printf("Data read via read: %s\n", read_data);
    } else {
        perror("Failed to read data");
    }
}

int main() {
    int i = 0;
    int fd = open("/dev/led_test", O_RDWR);
    if (fd < 0) {
        perror("Failed to open device");
        return EXIT_FAILURE;
    }
    for(; i < 10; i++)
    {
        test_led_control(fd);
    }
    for(i = 0; i < 5; i++)
    {
        test_large_data_transfer(fd);
    }


    close(fd);
    return EXIT_SUCCESS;
}
